package com.tencent.sr.iris.basic.mp.service.activity;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.comparator.CompareUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.tencent.sr.iris.activity.interfaces.enums.ActivityTypeEnum;
import com.tencent.sr.iris.activity.interfaces.enums.ShownTaskStatusEnum;
import com.tencent.sr.iris.activity.interfaces.request.IrisPaginationRequest;
import com.tencent.sr.iris.activity.interfaces.request.acticity.*;
import com.tencent.sr.iris.activity.interfaces.response.SearchAfterPaginationResponse;
import com.tencent.sr.iris.activity.interfaces.response.activity.*;
import com.tencent.sr.iris.basic.mp.common.enums.OutTaskStatusEnum;
import com.tencent.sr.iris.basic.mp.common.enums.TaskEndStatusEnum;
import com.tencent.sr.iris.basic.mp.common.enums.TaskEstimateStatusEnum;
import com.tencent.sr.iris.basic.mp.common.enums.UserTaskStatusEnum;
import com.tencent.sr.iris.basic.mp.common.util.SpelUtils;
import com.tencent.sr.iris.basic.mp.dependency.activity.UserTaskDependency;
import com.tencent.sr.iris.basic.mp.dependency.user.UserDependency;
import com.tencent.sr.iris.basic.mp.interfaces.request.*;
import com.tencent.sr.iris.basic.mp.interfaces.response.MpMultiTaskRecordResponse;
import com.tencent.sr.iris.basic.mp.interfaces.response.MpTaskRecordCommonResponse;
import com.tencent.sr.iris.basic.mp.interfaces.response.MpUserTaskRecordResponse;
import com.tencent.sr.iris.basic.mp.service.convert.MpUserTaskRecordConvert;
import com.tencent.sr.iris.user.core.service.interfaces.request.activity.IrisUserBatchQueryRequest;
import com.tencent.sr.iris.user.core.service.interfaces.request.level.UserLevelBatchRequest;
import com.tencent.sr.iris.user.core.service.interfaces.response.activity.IrisUserInfo;
import com.tencent.sr.iris.user.core.service.interfaces.response.level.UserLevelResponse;
import com.tencent.sr.rmall.common.request.PaginationRequest;
import com.tencent.sr.rmall.common.response.PaginationResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class UserTaskService {

    @Resource
    private UserTaskDependency userTaskDependency;

    @Resource
    private MpUserTaskRecordConvert taskRecordConvert;

    @Resource
    private UserDependency userDependency;

    /**
     * 会员任务情况分页列表
     *
     * @param request
     * @return
     */
    public SearchAfterPaginationResponse<MpUserTaskRecordResponse> page(PaginationRequest<MpUserTaskRecordRequest> request) {
        log.info("调用UserTaskService.page，入参：{}", JSON.toJSONString(request));
        IrisPaginationRequest<UserTaskRecordRequest> userTaskRecordRequest = taskRecordConvert.buildUserTaskRecordRequest(request);

        PaginationResponse<UserTaskRecordResponse> page = userTaskDependency.page(userTaskRecordRequest);
        SearchAfterPaginationResponse<MpUserTaskRecordResponse> mpPage = new SearchAfterPaginationResponse<>();
        mpPage.setPageSize(page.getPageSize());
        mpPage.setTotalCount(page.getTotalCount());
        mpPage.setPageNum(page.getPageNum());
        mpPage.setDataList(Collections.emptyList());

        List<UserTaskRecordResponse> dataList = page.getDataList();
        if (CollectionUtil.isEmpty(dataList)) {
            return mpPage;
        }
        //处理下级用户信息
        List<String> uidList = dataList.stream().map(UserTaskRecordResponse::getUid)
                .distinct().collect(Collectors.toList());
        Map<String, IrisUserInfo> userInfoMap = getUserInfoMap(uidList);
        Map<String, UserLevelResponse> userLevelMap = getUserLevelMap(uidList);

        Map<String, Map<String, List<UserTaskRecordResponse>>> map = groupBy(dataList);

        List<MpUserTaskRecordResponse> results = Lists.newArrayList();
        for (Map.Entry<String, Map<String, List<UserTaskRecordResponse>>> entry : map.entrySet()) {
            String uid = entry.getKey();

            IrisUserInfo irisUserInfo = Optional.ofNullable(userInfoMap.get(uid))
                    .orElseGet(IrisUserInfo::new);
            UserLevelResponse levelResponse = Optional.ofNullable(userLevelMap.get(uid))
                    .orElseGet(UserLevelResponse::new);

            MpUserTaskRecordResponse response = new MpUserTaskRecordResponse().setUid(uid)
                    .setUid(uid).setNickName(irisUserInfo.getNickName())
                    .setHeadUrl(irisUserInfo.getHeadUrl())
                    .setLevelId(levelResponse.getLevelId());
            List<MpMultiTaskRecordResponse> tasks = Lists.newArrayList();

            Map<String, List<UserTaskRecordResponse>> map1 = entry.getValue();
            for (Map.Entry<String, List<UserTaskRecordResponse>> listEntry : map1.entrySet()) {
                MpMultiTaskRecordResponse taskResponse = new MpMultiTaskRecordResponse();
                List<MpTaskRecordCommonResponse> commonResponses = handleTaskInfo(listEntry.getValue());
                if (commonResponses.size() == 1) {
                    taskResponse.setSingleRecord(commonResponses.get(0));
                } else {
                    taskResponse.setMultiRecord(commonResponses);
                }
                tasks.add(taskResponse);
            }

            //排序 邀请有礼---月月拿奖励---升级有礼
            sortTasks(tasks);
            response.setTasks(tasks);
            results.add(response);
        }

        mpPage.setDataList(results);
        return mpPage;
    }


    public SearchAfterPaginationResponse<MpUserTaskRecordResponse> getJuniorTaskRecordList(PaginationRequest<MpGetJuniorTaskRecordListRequest> request) {
        log.info("调用UserTaskService.getJuniorTaskRecordList，入参：{}", JSON.toJSONString(request));
        IrisPaginationRequest<GetJuniorTaskRecordListRequest> getJuniorTaskRecordListRequest = taskRecordConvert.buildJuniorTaskRecordListRequest(request);

        PaginationResponse<UserTaskRecordResponse> page = userTaskDependency.getJuniorTaskRecordList(getJuniorTaskRecordListRequest);
        SearchAfterPaginationResponse<MpUserTaskRecordResponse> mpPage = new SearchAfterPaginationResponse<>();
        mpPage.setPageSize(page.getPageSize());
        mpPage.setTotalCount(page.getTotalCount());
        mpPage.setPageNum(page.getPageNum());
        mpPage.setDataList(Collections.emptyList());

        List<UserTaskRecordResponse> dataList = page.getDataList();
        if (CollectionUtil.isEmpty(dataList)) {
            return mpPage;
        }
        //处理下级用户信息
        List<String> uidList = dataList.stream().map(UserTaskRecordResponse::getUid)
                .distinct().collect(Collectors.toList());
        Map<String, IrisUserInfo> userInfoMap = getUserInfoMap(uidList);
        Map<String, UserLevelResponse> userLevelMap = getUserLevelMap(uidList);

        LinkedHashMap<String, Map<String, List<UserTaskRecordResponse>>> map = reserveActivityRecord(dataList);

        List<MpUserTaskRecordResponse> results = Lists.newArrayList();
        for (Map.Entry<String, Map<String, List<UserTaskRecordResponse>>> entry : map.entrySet()) {
            String uid = entry.getKey();

            IrisUserInfo irisUserInfo = Optional.ofNullable(userInfoMap.get(uid))
                    .orElseGet(IrisUserInfo::new);
            UserLevelResponse levelResponse = Optional.ofNullable(userLevelMap.get(uid))
                    .orElseGet(UserLevelResponse::new);

            MpUserTaskRecordResponse response = new MpUserTaskRecordResponse().setUid(uid)
                    .setUid(uid).setNickName(irisUserInfo.getNickName())
                    .setHeadUrl(irisUserInfo.getHeadUrl())
                    .setLevelId(levelResponse.getLevelId());
            List<MpMultiTaskRecordResponse> tasks = Lists.newArrayList();

            Map<String, List<UserTaskRecordResponse>> map1 = entry.getValue();
            for (Map.Entry<String, List<UserTaskRecordResponse>> listEntry : map1.entrySet()) {
                MpMultiTaskRecordResponse taskResponse = new MpMultiTaskRecordResponse();
                List<UserTaskRecordResponse> userTaskRecordResponseList = listEntry.getValue();
                List<MpTaskRecordCommonResponse> commonResponses = handleTaskInfo(userTaskRecordResponseList);
                // 设置邀请时间
                if (CollectionUtils.isNotEmpty(userTaskRecordResponseList)) {
                    response.setInviteTime(userTaskRecordResponseList.get(0).getInviteTime());
                }
                if (commonResponses.size() == 1) {
                    taskResponse.setSingleRecord(commonResponses.get(0));
                } else {
                    taskResponse.setMultiRecord(commonResponses);
                }
                tasks.add(taskResponse);
            }
            response.setTasks(tasks);
            results.add(response);
        }
        mpPage.setDataList(results);
        return mpPage;
    }

    /**
     * 排序 邀请有礼---月月拿奖励---升级有礼
     *
     * @param tasks
     */
    private void sortTasks(List<MpMultiTaskRecordResponse> tasks) {
        tasks.sort(((o1, o2) -> {
            String t1 = Optional.ofNullable(o1.getSingleRecord()).map(MpTaskRecordCommonResponse::getActivityType)
                    .orElseGet(() -> o1.getMultiRecord().get(0).getActivityType());
            ActivityTypeEnum type1 = ActivityTypeEnum.getByCode(t1);

            String t2 = Optional.ofNullable(o2.getSingleRecord()).map(MpTaskRecordCommonResponse::getActivityType)
                    .orElseGet(() -> o2.getMultiRecord().get(0).getActivityType());
            ActivityTypeEnum type2 = ActivityTypeEnum.getByCode(t2);

            if (type1 == null) {
                return 1;
            }

            switch (type1) {
                case INVITE_GIFT:
                    return -1;
                case MONTH_GIFT:
                    if (!Objects.equals(type2, ActivityTypeEnum.INVITE_GIFT)) {
                        return -1;
                    }
                default:
                    return 1;
            }
        }));
    }

    /**
     * 处理任务信息
     *
     * @param responseList
     * @return
     */
    private List<MpTaskRecordCommonResponse> handleTaskInfo(List<UserTaskRecordResponse> responseList) {
        int size = responseList.size();
        List<MpTaskRecordCommonResponse> list = Lists.newArrayListWithCapacity(size);
        for (int idx = 0; idx < size; idx++) {
            UserTaskRecordResponse i = responseList.get(idx);
            MpTaskRecordCommonResponse commonResponse = taskRecordConvert.buildMpUserTaskRecordResponse(i);
            commonResponse.setStage(i.getTier());
            Integer code = TaskEndStatusEnum.getCodeByTaskEndTime(DateUtil.date(i.getCurrentTaskEndTime()), i.getCommissionTaskPlusDay());
            commonResponse.setCurrentTaskEndStatus(code);
            Integer inviteSeq = Optional.ofNullable(i.getInviteSeq()).orElse(0);
            Integer inviteLimit = Optional.ofNullable(i.getInviteLimit()).orElse(0);
            commonResponse.setCurrentLimited(inviteSeq > inviteLimit);
            list.add(commonResponse);
        }

        if (size == 1) {
            MpTaskRecordCommonResponse taskRecordCommonResponse = list.get(0);
            UserTaskRecordResponse userTaskRecordResponse = responseList.get(0);
            Integer singleTaskStatus = getSingleTaskStatus(userTaskRecordResponse);
            taskRecordCommonResponse.setUserTaskStatus(singleTaskStatus);
            if (userTaskRecordResponse.getSingleTaskInMultiActivity()) {
                taskRecordCommonResponse.setMultiTask(false);
            }
        }
        return list;
    }

    /**
     * 处理单任务状态
     *
     * @param response
     */
    private static Integer getSingleTaskStatus(UserTaskRecordResponse response) {
        //佣金相关判断待审核状态
        if (CompareUtil.compare(response.getTotalCommission(), 0) > 0
                && Objects.equals(response.getUserTaskStatus(), UserTaskStatusEnum.PROGRESS.getCode())
                && Objects.equals(response.getEstimateUserTaskStatus(), TaskEstimateStatusEnum.FINISHED.getCode())) {
            //任务状态审核中 = 佣金门槛不为空 && 预估状态已完成 && 任务状态未完成
            return (int) ShownTaskStatusEnum.AUDITING.getCode();
        }

        return (int) response.getUserTaskStatus();
    }

    /**
     * @param responseList
     */
    private static Integer getOutTaskStatus(List<UserTaskRecordResponse> responseList) {
        UserTaskRecordResponse firstTask = responseList.get(0);
        UserTaskRecordResponse secondTask = responseList.get(1);

        //一阶已完成不更新，佣金，有效分享数须以二阶为准
        Integer commission = secondTask.getCommission();
        Integer shareCount = secondTask.getShareCount();

        boolean firstThresholdGreater = CompareUtil.compare(commission, firstTask.getTotalCommission()) > 0
                && CompareUtil.compare(shareCount, firstTask.getTotalShareCount()) > 0;
        boolean secondThresholdGreater = CompareUtil.compare(commission, secondTask.getTotalCommission()) > 0
                && CompareUtil.compare(shareCount, secondTask.getTotalShareCount()) > 0;

        OutTaskStatusEnum statusEnum = OutTaskStatusEnum.getByStatusList(Arrays.asList(firstTask.getUserTaskStatus(), secondTask.getUserTaskStatus()),
                Arrays.asList(firstTask.getEstimateUserTaskStatus(), secondTask.getEstimateUserTaskStatus()), firstThresholdGreater, secondThresholdGreater);
        return Optional.ofNullable(statusEnum).map(OutTaskStatusEnum::getCode).orElse(null);
    }

    /**
     * 获取用户等级信息
     *
     * @param uidList
     * @return
     */
    private Map<String, UserLevelResponse> getUserLevelMap(List<String> uidList) {
        UserLevelBatchRequest levelBatchRequest = new UserLevelBatchRequest();
        levelBatchRequest.setUidList(uidList);
        List<UserLevelResponse> responses = userDependency.queryBatchUserLevel(levelBatchRequest);

        return responses.stream().collect(Collectors.toMap(
                UserLevelResponse::getUid, i -> i, (i1, i2) -> i1));
    }

    /**
     * 获取用户信息
     *
     * @param uidList
     * @return
     */
    private Map<String, IrisUserInfo> getUserInfoMap(List<String> uidList) {
        IrisUserBatchQueryRequest batchQueryRequest = new IrisUserBatchQueryRequest();
        batchQueryRequest.setUidList(uidList);

        List<IrisUserInfo> users = userDependency.batchQueryUserInfo(batchQueryRequest);
        return users.stream().filter(i -> StrUtil.isNotBlank(i.getUid())).collect(Collectors.toMap(
                IrisUserInfo::getUid, i -> i, (i1, i2) -> i1));
    }

    /**
     * 分组
     *
     * @param responses
     * @return
     */
    private Map<String, Map<String, List<UserTaskRecordResponse>>> groupBy(List<UserTaskRecordResponse> responses) {
        return responses.parallelStream()
                //下级uid分组
                .collect(Collectors.groupingBy(UserTaskRecordResponse::getUid,
                        //多任务活动分组
                        Collectors.groupingBy(i -> {
                                    if (StrUtil.isNotBlank(i.getGroupByExpression())) {
                                        return SpelUtils.parse(i.getGroupByExpression(), i, String.class);
                                    }
                                    return i.getBizId();
                                },
                                //根据阶段排序
                                //根据阶段排序
                                Collectors.collectingAndThen(Collectors.toList(),
                                        l -> l.stream().sorted(Comparator.comparing(UserTaskRecordResponse::getTier))
                                                .collect(Collectors.toList())
                                )
                        )));
    }

    /**
     * 长期激励统计
     *
     * @param request
     * @return
     */
    public LongTermAwardStaticResponse longTermAward(MpLongTermAwardStaticRequest request) {
        log.info("调用UserTaskService.longTermAward，入参：{}", JSON.toJSONString(request));
        LongTermAwardStaticRequest staticRequest = taskRecordConvert.buildLongTermAwardStaticRequest(request);
        return userTaskDependency.longTermAward(staticRequest);
    }

    /**
     * 长期激励统计
     *
     * @return
     */
    public UserActivityInfoResponse userActivityInfo() {
        return userTaskDependency.userActivityInfo();
    }

    /**
     * 余额流水活动信息
     *
     * @param request
     * @return
     */
    public FlowActivityInfoResponse queryFlowActivityInfo(MpFlowActivityInfoRequest request) {
        FlowActivityInfoRequest activityInfoRequest = new FlowActivityInfoRequest();
        activityInfoRequest.setTaskRecordId(request.getTaskRecordId());
        String taskId = request.getTaskId();
        if (StrUtil.isNotBlank(taskId)) {
            FlowActivityInfoRequest.LevelUpReq levelUpReq = new FlowActivityInfoRequest
                    .LevelUpReq().setTaskId(taskId);
            activityInfoRequest.setLevelUpReq(levelUpReq);
        }
        return userTaskDependency.queryFlowActivityInfo(activityInfoRequest);
    }

    /**
     * 统计所有活动奖励金
     *
     * @param activityStaticRequest
     * @return
     */
    public ActivityStaticResponse activityStatic(MpActivityStaticRequest activityStaticRequest) {
        log.info("调用UserTaskService.activityStatic，入参：{}", JSON.toJSONString(activityStaticRequest));
        ActivityStaticRequest staticRequest = taskRecordConvert.buildActivityStaticRequest(activityStaticRequest);
        return userTaskDependency.activityStatic(staticRequest);
    }

    /**
     * 保留活动记录顺序
     *
     * @param responses responses
     * @return 活动记录的排序后的任务记录
     */
    private LinkedHashMap<String, Map<String, List<UserTaskRecordResponse>>> reserveActivityRecord(List<UserTaskRecordResponse> responses) {
        LinkedHashMap<String, List<UserTaskRecordResponse>> reservedMap = new LinkedHashMap<>();
        for (UserTaskRecordResponse response : responses) {
            String uid = response.getUid();
            List<UserTaskRecordResponse> userTaskRecordResponseList = reservedMap.get(uid);
            if (CollectionUtil.isEmpty(userTaskRecordResponseList)) {
                userTaskRecordResponseList = new ArrayList<>();
                reservedMap.put(uid, userTaskRecordResponseList);
            }
            userTaskRecordResponseList.add(response);
        }

        LinkedHashMap<String, Map<String, List<UserTaskRecordResponse>>> resultMap = new LinkedHashMap<>();
        for(Map.Entry<String, List<UserTaskRecordResponse>> entry : reservedMap.entrySet()){
            List<UserTaskRecordResponse> userTaskRecordResponseList = entry.getValue();
            Map<String, List<UserTaskRecordResponse>> sortedMap = userTaskRecordResponseList.stream().collect(
                    //多任务活动分组
                    Collectors.groupingBy(i -> {
                                if (StrUtil.isNotBlank(i.getGroupByExpression())) {
                                    return SpelUtils.parse(i.getGroupByExpression(), i, String.class);
                                }
                                return i.getBizId();
                            },
                            //根据阶段排序
                            //根据阶段排序
                            Collectors.collectingAndThen(Collectors.toList(),
                                    l -> l.stream().sorted(Comparator.comparing(UserTaskRecordResponse::getTier))
                                            .collect(Collectors.toList())
                            )
                    ));
            resultMap.put(entry.getKey(), sortedMap);
        }
        return resultMap;
    }
}
